package site.jlopen.service.imp;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import site.jlopen.domain.data.event.KusciaDataColumnEvent;
import site.jlopen.domain.data.event.KusciaDataEvent;
import site.jlopen.domain.job.KusciaJob;
import site.jlopen.domain.job.event.KusciaJobEvent;
import site.jlopen.domain.node.event.KusciaNodeEvent;
import site.jlopen.domain.project.KusciaProject;
import site.jlopen.domain.project.KusciaProjectFlow;
import site.jlopen.domain.project.KusciaProjectInvite;
import site.jlopen.domain.project.KusciaProjectRead;
import site.jlopen.domain.project.event.KusciaProjectEvent;
import site.jlopen.domain.project.event.KusciaProjectFlowEvent;
import site.jlopen.domain.project.event.KusciaProjectInviteEvent;
import site.jlopen.domain.project.event.KusciaProjectReadEvent;
import site.jlopen.entity.BaseResponse;
import site.jlopen.entity.req.ProjectReq;
import site.jlopen.entity.vo.project.ProjectInvite;
import site.jlopen.entity.vo.project.ProjectInvite.ProjectInviteData;
import site.jlopen.entity.vo.project.ProjectInvite.ProjectInviteDataColumn;
import site.jlopen.mapper.data.KusciaDataColumnMapper;
import site.jlopen.mapper.data.KusciaDataMapper;
import site.jlopen.mapper.job.KusciaJobMapper;
import site.jlopen.mapper.node.KusciaNodeMapper;
import site.jlopen.mapper.project.KusciaProjectFlowMapper;
import site.jlopen.mapper.project.KusciaProjectInviteMapper;
import site.jlopen.mapper.project.KusciaProjectMapper;
import site.jlopen.mapper.project.KusciaProjectReadMapper;
import site.jlopen.service.intf.data.DataService;
import site.jlopen.service.intf.project.ProjectService;
import site.jlopen.utils.id.IdUtils;

@Service
public class ProjectServiceImpl implements ProjectService {
	
	@Autowired
	private KusciaProjectMapper projectMapper;
	@Autowired
	private KusciaProjectInviteMapper inviteMapper;
	@Autowired
	private KusciaNodeMapper nodeMapper;
	@Autowired
	private KusciaProjectFlowMapper flowMapper;
	@Autowired
	private KusciaProjectReadMapper readMapper;
	@Autowired
	private KusciaDataMapper dataMapper;
	@Autowired
	private DataService dataService;
	@Autowired
	private KusciaDataColumnMapper columnMapper;
	@Autowired
	private KusciaJobMapper jobMapper;

	@Override
	public BaseResponse<String> create(Long userId, ProjectReq req) {
		if(null == req.getId()) {
			req.setId(IdUtils.SnowFlakeId());
		}
		KusciaProject info = projectMapper.selectByKey(req.getId());
		int row = 0;
		if(null == info) {
			info = new KusciaProject()
			.setProjectUserId(userId)
			.setProjectId(req.getId())
			.setProjectName(req.getName())
			.setProjectDesc(req.getDesc())
			.setProjectModel(req.getModel())
			.setProjectChannel(req.getChannel())
			.setProjectFinish(0)
			.setProjectNodeId(req.getOwnerId())
			.setProjectStatus(0)
			.setProjectCreate(new Date())
			;
			row = projectMapper.insertSelective(info);
			if(row > 0) {
				// 默认一个数据流
				saveFlow(req.getId(), "默认训练流");
				List<KusciaProjectInvite> invites = new ArrayList<KusciaProjectInvite>();
				invites.add(new KusciaProjectInvite()
						.setInviteId(IdUtils.SnowFlakeId())
						.setInviteProjectId(req.getId())
						.setInviteNodeId(req.getOwnerId())
						.setInviteStatus(1)
						.setInviteRole("owner")
						.setInviteCreate(new Date())
						);
				List<Long> nodes = req.getInviteNodes();
				for (Long node : nodes) {
					invites.add(new KusciaProjectInvite()
							.setInviteId(IdUtils.SnowFlakeId())
							.setInviteProjectId(req.getId())
							.setInviteNodeId(node)
							.setInviteStatus(1)
							.setInviteRole("partner")
							.setInviteCreate(new Date())
							);
				}
				inviteMapper.insertBatch(invites);
			}
		}else {
			info.setProjectModified(new Date());
			row = projectMapper.updateSelective(info);
		}
		if (row > 0) {
			return new BaseResponse<String>().success("创建成功");
		}
		return new BaseResponse<String>().error("保存失败");
	}

	@Override
	public KusciaProjectEvent projectInfo(Long projectId) {
		return projectMapper.selectByKey(projectId);
	}

	@Override
	public List<KusciaProjectEvent> list(Long userId) {
		Map<String, Object> records = new HashMap<String, Object>();
		records.put("projectUserId", userId);
		List<KusciaProjectEvent> list = projectMapper.selectAllNotPage(records);
		for (KusciaProjectEvent project : list) {
			KusciaNodeEvent node = nodeMapper.selectByKey(project.getProjectNodeId());
			if(null != node) {
				project.setNodeCode(node.getNodeCode());
			}
			Map<String, Object> record = new HashMap<String, Object>();
			record.put("inviteProjectId", project.getProjectId());
			record.put("inviteRole", "partner");
			List<KusciaProjectInviteEvent> invites = inviteMapper.selectAllNotPage(record);
			for (KusciaProjectInviteEvent invite : invites) {
				KusciaNodeEvent ivnode = nodeMapper.selectByKey(invite.getInviteNodeId());
				invite.setNode(ivnode);
			}
			project.setInvites(invites);
			KusciaJobEvent jobEvent = jobMapper.selectByInfo(new KusciaJob().setJobProjectId(project.getProjectId()));
			project.setJob(jobEvent);
		}
		return list;
	}

	@Override
	public List<ProjectInvite> inviteList(Long projectId) {
		List<ProjectInvite> list = new ArrayList<ProjectInvite>();
		Map<String, Object> record = new HashMap<String, Object>();
		record.put("inviteProjectId", projectId);
		List<KusciaProjectInviteEvent> rows = inviteMapper.selectAllNotPage(record);
		/*for (KusciaProjectInviteEvent invite : list) {
			KusciaNodeEvent node = nodeMapper.selectByKey(invite.getInviteNodeId());
			if(null != node) {
				invite.setNodeCode(node.getNodeCode());
			}
			invite.setReadInfo(getProjectRead(invite.getInviteId()));
		}*/
		for (KusciaProjectInviteEvent invite : rows) {
			KusciaNodeEvent node = nodeMapper.selectByKey(invite.getInviteNodeId());
			ProjectInviteData dataVo = null;
			KusciaProjectReadEvent read = readMapper.selectByInfo(new KusciaProjectRead().setReadInviteId(invite.getInviteId()));
			if(null != read) {
				KusciaDataEvent data = dataMapper.selectByKey(read.getReadDataId());
				Map<String, Object> cmap = new HashMap<String, Object>();
				cmap.put("columnDataId", data.getDataId());
				List<KusciaDataColumnEvent> cList = columnMapper.selectAllNotPage(cmap);
				List<ProjectInviteDataColumn> cVos = new ArrayList<ProjectInviteDataColumn>();
				for (KusciaDataColumnEvent column : cList) {
					cVos.add(new ProjectInviteDataColumn(column));
				}
				dataVo = new ProjectInviteData(data.getDataTitle(), data.getDataDomaindataId(),  cVos);
			}
			ProjectInvite inviteVo = ProjectInvite.builder()
					.nodeCode(node.getNodeCode())
					.nodeId(invite.getInviteNodeId())
					.inviteId(invite.getInviteId())
					.data(dataVo)
					.build();
			list.add(inviteVo);
		}
		return list;
	}

	private KusciaProjectReadEvent getProjectRead(Long inviteId) {
		KusciaProjectReadEvent read = readMapper.selectByInfo(new KusciaProjectRead().setReadInviteId(inviteId));
		if(null == read)return null;
		KusciaDataEvent data = dataMapper.selectByKey(read.getReadDataId());
		Map<String, Object> cmap = new HashMap<String, Object>();
		cmap.put("columnDataId", data.getDataId());
		List<KusciaDataColumnEvent> cList = columnMapper.selectAllNotPage(cmap);
		data.setColumnList(cList);
		//read.setData(data);
		return read;
		
	}
	
	@Override
	public BaseResponse<String> finish(Long projectId) {
		KusciaProjectEvent info = projectMapper.selectByKey(projectId);
		info.setProjectFinish(1);
		int row = projectMapper.updateSelective(info);
		if(row > 0) {
			return new BaseResponse<String>().success("已归档");
		}
		return new BaseResponse<String>().error("归档失败");
	}

	@Override
	public BaseResponse<String> changeInvite(Long inviteId) {
		KusciaProjectInviteEvent info = inviteMapper.selectByKey(inviteId);
		info.setInviteStatus(1);
		int row = inviteMapper.updateSelective(info);
		if(row > 0) {
			return new BaseResponse<String>().success("已授权");
		}
		return new BaseResponse<String>().error("授权失败");
	}

	@Override
	public BaseResponse<String> clearing(Long projectId) {
		int row = projectMapper.clearingProject(projectId);
		if(row > 0) {
			
		}
		return new BaseResponse<String>().success("成功释放所有数据");
	}

	@Override
	public List<KusciaProjectFlowEvent> getFlows(Long projectId) {
		Map<String, Object> record = new HashMap<String, Object>();
		record.put("flowProjectId", projectId);
		List<KusciaProjectFlowEvent> list = flowMapper.selectAllNotPage(record);
		return list;
	}

	@Override
	public BaseResponse<String> removeFlow(Long flowId) {
		int row = flowMapper.deleteByKey(flowId);
		return new BaseResponse<String>().dbRes(row, "移除成功");
	}

	@Override
	public BaseResponse<String> saveFlow(Long projectId, String flowTitle) {
		int row = flowMapper.insertSelective(new KusciaProjectFlow()
				.setFlowId(IdUtils.SnowFlakeId())
				.setFlowProjectId(projectId)
				.setFlowTitle(flowTitle)
				.setFlowCreate(new Date())
				);
		return new BaseResponse<String>().dbRes(row, "创建成功");
	}

	@Override
	public BaseResponse<String> saveReadData(Long projectId, Long flowId, Long nodeId, Long dataId) {
		KusciaProjectInviteEvent inviteEvent =  inviteMapper.selectByInfo(new KusciaProjectInvite()
				.setInviteProjectId(projectId).setInviteNodeId(nodeId));
		KusciaProjectRead readEvent = readMapper.selectByInfo(new KusciaProjectRead()
				.setReadInviteId(inviteEvent.getInviteId()).setReadDataId(dataId));
		if(null != readEvent) {
			return new BaseResponse<String>().error("请不要重复授权");
		}
		readEvent = new KusciaProjectRead();
		readEvent.setReadId(IdUtils.SnowFlakeId());
		readEvent.setReadDataId(dataId);
		readEvent.setReadInviteId(inviteEvent.getInviteId());
		readEvent.setReadCreate(new Date());
		int row = readMapper.insertSelective(readEvent);
		// 判断是否全部节点已经选择授权的数据，那么久开始互相授权数据给对方节点
		Long reads = readMapper.selectProjectReads(projectId);
		Map<String, Object> record = new HashMap<String, Object>();
		record.put("inviteProjectId", projectId);
		List<KusciaProjectInviteEvent>  invites = inviteMapper.selectAllNotPage(record);
		if(null != reads && null != invites && reads.intValue() == invites.size()) {
			for (KusciaProjectInviteEvent invite : invites) {
				for (KusciaProjectInviteEvent inviteTarget : invites) {
					if(invite.getInviteNodeId().compareTo(inviteTarget.getInviteNodeId()) != 0) {
						KusciaProjectRead readData = readMapper.selectByInfo(new KusciaProjectRead()
								.setReadInviteId(invite.getInviteId()));
						dataService.refreshDataGrant(flowId, invite.getInviteNodeId(), readData.getReadDataId(), inviteTarget.getInviteNodeId());
					}
				}
			}
		}
		return new BaseResponse<String>().dbRes(row, "授权成功");
	}

	

}
